'''
Created on Mar 11, 2014

@author: vietphv
'''

class ASTNode(object):
    """ A node of an abstract syntax tree
    """
    def __init__(self, label, children=[]):
        """
        @param label: label of node
        @param children: a list of children nodes
        """
        self._label = label
        self._children = children
    
    def size(self):
        """ Number of children
        """
        return len(self._children)
    
    def children(self, k=None):
        """ Get children of node
        """
        if k == None:
            return self._children
        else:
            return self._children[k]
    
    def label(self):
        """ Get the label of node
        """
        return self._label
    
    
class PropTree(ASTNode):
    def __init__(self, label, children=[]):
        ASTNode.__init__(self, label, children)
        
    def show(self, p=None):
        if p is None:
            self.show(self)
        elif p.label() == "$":
            print p.children()[0]
        else:
            for c in p.children():
                c.show()
                
    def toString(self, p=None):
        if p == None:
            return self.toString(self)
        else:
            if p.label() == "$":
                return str(p.children()[0])
            else:
                op = " %s " % p.label()
                s = op.join(x.toString() for x in p.children())
                if p.size() > 1:
                    return "(%s)" % s
                else:
                    return s
                
    def translate(self, p, defis=[], K=[]):
        if p.label() == '$':
            if p.children(0).direct():
                pred = p.children(0).translate()
            else:
                if len(K) == 0:
                    k = 1
                else:
                    k = K[len(K) - 1] + 1
                pred, d = p.children(0).translate(k)
                K.append(k)
                defis.append(d)
            return pred 
        else:
            op = " %s " % p.label()
            s = op.join(self.translate(x, defis, K) for x in p.children())
            if p.size() > 1:
                return "(%s)" % s
            else:
                return s
                
    def export(self, dest='pred.py'):
        fhandle = open(dest, 'a')
        defis = []
        K = []
        F = self.translate(self, defis, K)
        if len(defis)==0:
            formula = "formula='%s'\n\n" %F
        else:
            formula = "formula=%s\n\n" %F
        definitions = "\n".join(d for d in defis)
        fhandle.write("\n" + formula)
        fhandle.write(definitions)
        fhandle.close()
        print "The property is exported to file '%s'." % dest
